/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.debugger.jpda;
import java.beans.*;
import java.io.*;
import java.text.MessageFormat;
import java.awt.Component;
import java.awt.Insets;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import com.sun.jdi.*;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.Connector.Argument;
import com.sun.jdi.event.*;
import com.sun.jdi.request.*;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.text.Line;
import org.openide.TopManager;
import org.openide.NotifyDescriptor;
import org.openide.cookies.LineCookie;
import org.openide.debugger.*;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.Repository;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileSystemCapability;
import org.openide.filesystems.EnvironmentNotSupportedException;
import org.openide.windows.InputOutput;
import org.openide.windows.OutputWriter;
import org.openide.execution.NbProcessDescriptor;
import org.openide.execution.NbClassPath;
import org.openide.util.MapFormat;
import org.openide.util.NbBundle;
import org.netbeans.modules.debugger.support.AbstractDebugger;
import org.netbeans.modules.debugger.support.CoreBreakpoint;
import org.netbeans.modules.debugger.support.AbstractThreadGroup;
import org.netbeans.modules.debugger.support.AbstractThread;
import org.netbeans.modules.debugger.support.ProcessDebuggerInfo;
import org.netbeans.modules.debugger.support.ProcessDebuggerType;
import org.netbeans.modules.debugger.support.PrintAction;
import org.netbeans.modules.debugger.support.DebuggerInfoProducer;
import org.netbeans.modules.debugger.support.util.Validator;
import org.netbeans.modules.debugger.jpda.util.*;
/**
* Main Corona debugger class
*
* @author Jan Jancura
* @version 0.47, May 26, 1998
*/
public class JPDADebugger extends AbstractDebugger implements Executor {
// static ........................................................................
static final long serialVersionUID = 2797853329739651906L;
/** bundle to obtain text information from */
static ResourceBundle bundle = org.openide.util.NbBundle.getBundle
(JPDADebugger.class);
private static CoreBreakpoint.Event[] breakpointEvents;
private static CoreBreakpoint.Action[] breakpointActions;
private static Random random = new Random ();
static {
breakpointEvents = new CoreBreakpoint.Event[] {
// new InstanceCounter (),
new LineBreakpoint (),
new MethodBreakpoint (),
new ExceptionBreakpoint (),
new VariableBreakpoint (),
new ThreadBreakpoint (),
new ClassBreakpoint ()
};
breakpointActions = new CoreBreakpoint.Action[] {
};
}
// variables .................................................................
transient VirtualMachine virtualMachine = null;
transient EventRequestManager requestManager = null;
transient protected ThreadManager threadManager;
transient protected Operator operator;
transient private Process process;
transient StepRequest stepRequest;
private transient MethodEntryRequest findSourceMER;
private transient StepRequest findSourceSR;
private transient int findSourceCounter = 0;
transient private Thread debuggerThread;
private transient AttachingConnector connector;
private transient Map args;
private transient String mainClassName;
private transient String stopClassName;
// threads
private transient JPDAThread currentThread = null;
protected transient JPDAThreadGroup threadGroup = new JPDAThreadGroup (null);
private transient boolean stopOnMain = false;
private transient DebuggerInfo debuggerInfo;
private static transient String [] stopMethodNames = {"main", "start", "init", "<init>"}; // NOI18N
private transient CoreBreakpoint [] breakpointMain = null;
// init .......................................................................
public JPDADebugger () {
this (false, null);
}
public JPDADebugger (boolean multisession, Validator validator) {
super (multisession, validator);
}
/**
* Deserializes debugger.
*/
protected void setDebugger (AbstractDebugger debugger) {
super.setDebugger (debugger);
}
// Debugger implementation .................................................................
/** Starts the debugger. The method stops the current debugging (if any)
* and takes information from the provided info (containing the class to start and
* arguments to pass it and name of class to stop debugging in) and starts
* new debugging session.
*
* @param info debugger info about class to start
* @exception DebuggerException if an error occures during the start of the debugger
*/
public void startDebugger (DebuggerInfo info) throws DebuggerException {
debuggerInfo = info;
if (virtualMachine != null)
finishDebugger ();
stopOnMain = info.getStopClassName () != null;
mainClassName = info.getClassName (); //S ystem.out.println ("JPDADebugger stop on " + info.getStopClassName ()); // NOI18N
// open output window ...
super.startDebugger (info);
// stop on main
if (stopOnMain) {
try {
String stopClassName = debuggerInfo.getStopClassName ();
AbstractDebugger d = (AbstractDebugger) TopManager.getDefault ().getDebugger ();
breakpointMain = new CoreBreakpoint [stopMethodNames.length];
for (int x = 0; x < breakpointMain.length; x++) {
breakpointMain [x] = (CoreBreakpoint) d.createBreakpoint (true);
breakpointMain [x].setClassName (""); // NOI18N
breakpointMain [x].setMethodName (stopMethodNames [x]); // NOI18N
CoreBreakpoint.Action[] a = breakpointMain [x].getActions ();
int i, ii = a.length;
for (i = 0; i < ii; i ++)
if (a [i] instanceof PrintAction) {
((PrintAction) a [i]).setPrintText (bundle.getString ("CTL_Stop_On_Main_print_text"));
}
breakpointMain [x].setClassName (stopClassName);
}
addPropertyChangeListener (new PropertyChangeListener () {
public void propertyChange (PropertyChangeEvent ev) {
if (ev.getPropertyName ().equals (PROP_STATE)) {
if ((((Integer)ev.getNewValue ()).intValue () == DEBUGGER_STOPPED) ||
(((Integer)ev.getNewValue ()).intValue () == DEBUGGER_NOT_RUNNING)) {
if (breakpointMain != null) {
for (int x = 0; x < breakpointMain.length; x++)
breakpointMain [x].remove();
breakpointMain = null;
}
removePropertyChangeListener(this);
}
}
}
});
} catch (DebuggerException e) {
e.printStackTrace();
}
}
// start & init remote debugger ............................................
boolean launch = false;
if (info instanceof ReconnectDebuggerInfo) {
virtualMachine = reconnect ((ReconnectDebuggerInfo) info);
} else
if (info instanceof RemoteDebuggerInfo) {
virtualMachine = connect ((RemoteDebuggerInfo) info);
} else {
virtualMachine = launch (info);
process = virtualMachine.process ();
showOutput (process, STD_OUT, STD_OUT);
connectInput (process);
launch = true;
}
requestManager = virtualMachine.eventRequestManager ();
operator = new Operator (
virtualMachine,
launch ?
new Runnable () {
public void run () {
startDebugger ();
}
} :
null,
new Runnable () {
public void run () {
try {
finishDebugger ();
} catch (DebuggerException e) {
}
}
}
);
operator.start ();
if (!launch) startDebugger ();
}
/**
* Finishes debugger.
*/
public void finishDebugger () throws DebuggerException {
if (breakpointMain != null) {
for (int x = 0; x < breakpointMain.length; x++)
breakpointMain [x].remove ();
breakpointMain = null;
}
try {
if (virtualMachine != null) virtualMachine.exit (0);
} catch (VMDisconnectedException e) {
}
if (threadManager != null) threadManager.finish ();
if (debuggerThread != null) {
debuggerThread.interrupt ();
debuggerThread.stop ();
}
super.finishDebugger ();
}
/**
* Trace into.
*/
synchronized public void traceInto () throws DebuggerException {
if (virtualMachine == null) return;
removeStepRequest ();
try {
setLastAction (ACTION_TRACE_INTO);
stepRequest = requestManager.createStepRequest (
currentThread.getThreadReference (),
StepRequest.STEP_LINE,
StepRequest.STEP_INTO
);
stepRequest.addCountFilter (1);
stepRequest.putProperty ("traceInto", "traceInto"); // NOI18N
stepRequest.setSuspendPolicy (EventRequest.SUSPEND_ALL);
operator.register (stepRequest, this);
stepRequest.enable ();
virtualMachine.resume ();
super.traceInto ();
} catch (DuplicateRequestException e) {
e.printStackTrace ();
}
}
/**
* Trace over.
*/
synchronized public void traceOver () throws DebuggerException {
if (virtualMachine == null) return;
removeStepRequest ();
try {
setLastAction (ACTION_TRACE_OVER);
stepRequest = requestManager.createStepRequest (
currentThread.getThreadReference (),
StepRequest.STEP_LINE,
StepRequest.STEP_OVER
);
stepRequest.addCountFilter (1);
stepRequest.setSuspendPolicy (EventRequest.SUSPEND_ALL);
operator.register (stepRequest, this);
stepRequest.enable ();
virtualMachine.resume ();
super.traceOver ();
} catch (DuplicateRequestException e) {
e.printStackTrace ();
}
}
/**
* Go.
*/
synchronized public void go () throws DebuggerException {
if (virtualMachine == null) return;
setLastAction (ACTION_GO);
removeStepRequest ();
virtualMachine.resume ();
threadGroup.refresh ();
super.go ();
}
/**
* Step out.
*/
synchronized public void stepOut () throws DebuggerException {
if (virtualMachine == null) return;
removeStepRequest ();
try {
setLastAction (ACTION_STEP_OUT);
stepRequest = requestManager.createStepRequest (
currentThread.getThreadReference (),
StepRequest.STEP_LINE,
StepRequest.STEP_OUT
);
stepRequest.addCountFilter (1);
stepRequest.setSuspendPolicy (EventRequest.SUSPEND_ALL);
operator.register (stepRequest, this);
stepRequest.enable ();
virtualMachine.resume ();
super.stepOut ();
} catch (DuplicateRequestException e) {
e.printStackTrace ();
}
}
// WATCHES ..............................................................
/** Creates new uninitialized watch. The watch is visible (not hidden).
*
* @return new uninitialized watch
*/
public Watch createWatch () {
JPDAWatch w = new JPDAWatch (this);
watch.addElement (w);
fireWatchCreated (w);
return w;
}
/** Creates a watch its expression is set to initial value. Also
* allows to create a watch not presented to the user, for example
* for internal usage in the editor to obtain values of variables
* under the mouse pointer.
*
* @param expr expresion to watch for
* @param hidden allows to specify whether the watch should be presented
* to the user or not (be only of internal usage of the IDE).
* @return new watch
*/
public Watch createWatch (String expr, boolean hidden) {
JPDAWatch w = new JPDAWatch (this);
if (!hidden) watch.addElement (w);
w.setVariableName (expr);
if (!hidden) fireWatchCreated (w);
return w;
}
// AbstractDebugger implementation ..................................................
// properties ........................
/**
* Returns version of this debugger.
*/
public String getVersion () {
return bundle.getString ("CTL_Debugger_version");
/* if (virtualMachine != null)
return virtualMachine.versionDescription () + " (" +
virtualMachine.majorVersion () + "/" +
virtualMachine.minorVersion () + ")";
else
return bundle.getString ("CTL_Debugger_version");*/
}
/**
* Returns size of memory.
*/
public int getTotalMemory () throws DebuggerException {
if (virtualMachine == null) return 0;
return 0;
}
/**
* Returns size of free memory.
*/
public int getFreeMemory () throws DebuggerException {
if (virtualMachine == null) return 0;
return 0;
}
/**
* @return newly constructed string containing classpath obtained from filesystems
*/
public String getClasspath () {
return ""; // NOI18N
}
/**
* @return Connect Panel for this version of debugger.
*/
public JComponent getConnectPanel () {
return new Connector ();
}
/**
* @return name of proces for given DebuggerInfo.
*/
public String getProcessName (DebuggerInfo info) {
if (info instanceof RemoteDebuggerInfo) {
if ( ((RemoteDebuggerInfo) info).getConnector ().
transport ().name ().equals ("dt_shmem")
) {
Argument a = (Argument) ((RemoteDebuggerInfo) info).getArgs ().
get ("name");
if (a == null)
return "localhost:???";
else
return "localhost:" + a.value ();
} else
if ( ((RemoteDebuggerInfo) info).getConnector ().
transport ().name ().equals ("dt_socket")
) {
Argument name = (Argument) ((RemoteDebuggerInfo) info).getArgs ().
get ("hostname");
Argument port = (Argument) ((RemoteDebuggerInfo) info).getArgs ().
get ("port");
return ((name == null) ? "???:" : (name.value () + ":")) +
((port == null) ? "???" : (port.value ()));
} else
return "???";
} else
return (info.getStopClassName () != null) ? info.getStopClassName () :
info.getClassName ();
}
/**
* @return name of location for given DebuggerInfo.
*/
public String getLocationName (DebuggerInfo info) {
if (info instanceof RemoteDebuggerInfo) {
if ( ((RemoteDebuggerInfo) info).getConnector ().transport ().
name ().equals ("dt_shmem")
) {
return "localhost";
} else
if ( ((RemoteDebuggerInfo) info).getConnector ().transport ().
name ().equals ("dt_socket")
) {
Argument name = (Argument) ((RemoteDebuggerInfo) info).getArgs ().
get ("hostname");
return name == null ? "localhost" : name.value ();
} else
return "localhost";
} else
return "localhost";
}
/**
* Returns true - JPDADebugger supports evaluation of expressions.
*/
public boolean supportsExpressions () {
return true;
}
// breakpoints ........................
/**
* Returns events available for this version of debugger.
*/
public CoreBreakpoint.Event[] getBreakpointEvents () {
return breakpointEvents;
}
/**
* Returns actions available for this version of debugger.
*/
public CoreBreakpoint.Action[] getBreakpointActions () {
return breakpointActions;
}
// threads ........................
/**
* Returns root of all threads.
*/
public AbstractThreadGroup getThreadGroupRoot () {
return threadGroup;
}
/**
* Returns current thread or null.
*/
public AbstractThread getCurrentThread () {
return currentThread;
}
/**
* Sets current thread. If thread is null, unsets curent thread.
*/
public void setCurrentThread (AbstractThread thread) {
if (currentThread == thread) return;
Object old = currentThread;
currentThread = (JPDAThread) thread;
firePropertyChange (PROP_CURRENT_THREAD, old, thread);
}
// interface Executor .....................................................................
/**
* Executes breakpoint hit event.
*/
public void exec (com.sun.jdi.event.Event ev) {
//S ystem.out.println ("exec "); // NOI18N
removeStepRequest ();
StepEvent event = (StepEvent) ev;
ThreadReference tr = event.thread ();
Location loc = event.location ();
int ln = -1;
String methodName = "?"; // NOI18N
String className = "?"; // NOI18N
String lineNumber = "?"; // NOI18N
String threadName = tr.name ();
Line l = null;
if (loc != null) {
if (loc.method () != null)
methodName = loc.method ().name ();
className = loc.declaringType ().name ();
ln = loc.lineNumber ();
if (ln >= 0)
lineNumber = "" + loc.lineNumber ();
}
if (ln != -1)
try {
l = Utils.getLineForSource (
className,
loc.sourceName (),
ln
);
} catch (AbsentInformationException e) {
l = Utils.getLine (
className,
ln
);
}
if (resolveCanBeCurrent (tr, l))
// if this line can not be current resolveCanBeCurrent () calls stepOver
return;
// line can be current
if ( (l == null) &&
(getLastAction () == ACTION_TRACE_INTO)
)
// try to find another "intelligent" line of code
traceToSourceCode (tr);
// you know - intelligent means that one with source code
else {
makeCurrent (
threadName,
className,
methodName,
lineNumber,
l != null,
tr
);
operator.stopRequest ();
}
}
// support for multisession debugging ................................................................
/**
* Disconnects from running debugged process.
*/
public void disconnect () throws DebuggerException {
if (breakpointMain != null) {
for (int x = 0; x < breakpointMain.length; x++)
breakpointMain [x].remove ();
breakpointMain = null;
}
try {
if (virtualMachine != null) virtualMachine.dispose ();
} catch (VMDisconnectedException e) {
}
if (threadManager != null) threadManager.finish ();
if (debuggerThread != null) {
debuggerThread.interrupt ();
debuggerThread.stop ();
}
super.finishDebugger ();
}
/**
* Reconnects to disconnected Virtual Machine.
*/
public void reconnect () throws DebuggerException {
startDebugger (new ReconnectDebuggerInfo (
connector,
args
));
}
// helper private methods .........................................................................
/**
* Finds the first executed line with source code.
*/
public void traceToSourceCode (ThreadReference thread) {
//S ystem.out.println ("Start finding!!! "); // NOI18N
// create Step Request for searching a source code
try {
findSourceSR = requestManager.createStepRequest (
thread,
StepRequest.STEP_LINE,
StepRequest.STEP_OUT
);
findSourceSR.addCountFilter (1);
findSourceSR.setSuspendPolicy (EventRequest.SUSPEND_ALL);
operator.register (findSourceSR, this);
findSourceSR.enable ();
} catch (DuplicateRequestException e) {
e.printStackTrace ();
}
// create Method Entry Request for searching a source code
findSourceMER = requestManager.createMethodEntryRequest ();
findSourceMER.setSuspendPolicy (EventRequest.SUSPEND_ALL);
findSourceMER.addThreadFilter (thread);
findSourceCounter = 0;
operator.register (findSourceMER, new Executor () {
public void exec (com.sun.jdi.event.Event event) {
if (findSourceCounter == 500) {
// finding source takes a long time
operator.resume ();
if (findSourceMER != null) {
requestManager.deleteEventRequest (findSourceMER);
findSourceMER = null;
}
return;
}
findSourceCounter++;
Location loc = ((MethodEntryEvent) event).location ();
if (loc == null) {
// no line => continue finding
operator.resume ();
return;
}
String className = loc.declaringType ().name ();
int ln = loc.lineNumber ();
//S ystem.out.println ("FIND " + className + " : " + ln); // NOI18N
try {
Line l = null;
if ( (l = Utils.getLineForSource (className, loc.sourceName (), ln))
== null
) {
// no line => continue finding
operator.resume ();
return;
}
// WOW I have a nice line!
ThreadReference tr = ((MethodEntryEvent) event).thread ();
if (resolveCanBeCurrent (tr, l))
// if can not be current => steps to some line
return;
// line can be current!
String threadName = tr.name ();
String methodName = loc.method () != null ? loc.method ().name () : ""; // NOI18N
String lineNumber = ln == -1 ? "?" : "" + ln; // NOI18N
makeCurrent (
threadName,
className,
methodName,
lineNumber,
true,
tr
);
operator.stopRequest ();
} catch (AbsentInformationException e) {
}
}
});
findSourceMER.enable ();
operator.resume ();
return;
}
/**
* if this line can not be current => stepOver & return true.
* return false on the other hand.
*/
boolean resolveCanBeCurrent (ThreadReference tr) {
try {
Location l = tr.frame (0).location ();
if (l == null) return false;
return resolveCanBeCurrent (
tr,
Utils.getLineForSource (
l.declaringType ().name (),
l.sourceName (),
l.lineNumber ()
)
);
} catch (Exception e) {
}
return false;
}
/**
* If this line can not be current => stepOver & return true.
* {support for non java languages}
*
* return false on the other hand.
*/
boolean resolveCanBeCurrent (ThreadReference tr, Line l) {
if ( (l != null) &&
(!canBeCurrent (l, false))
) {
try {
removeStepRequest ();
findSourceSR = requestManager.createStepRequest (
tr,
StepRequest.STEP_LINE,
StepRequest.STEP_OVER
);
findSourceSR.addCountFilter (1);
findSourceSR.setSuspendPolicy (EventRequest.SUSPEND_ALL);
operator.register (findSourceSR, this);
findSourceSR.enable ();
operator.resume ();
} catch (DuplicateRequestException e) {
e.printStackTrace ();
}
return true;
}
return false;
}
/**
* Sets curent line. It means: change debugger state to stopped,
* shows message, sets current thread and updates watches.
*/
private void makeCurrent (
final String threadName,
final String className,
final String methodName,
final String lineNumber,
final boolean hasSource,
final ThreadReference tr
) {
setDebuggerState (DEBUGGER_STOPPED);
SwingUtilities.invokeLater (new Runnable () {
public void run () {
// show message
if (isFollowedByEditor ()) {
if (hasSource) {
println (
new MessageFormat (bundle.getString ("CTL_Thread_stopped")).
format (
new Object[] {
threadName,
className,
methodName,
lineNumber
}
),
ERR_OUT + STL_OUT
);
} else {
println (
new MessageFormat (bundle.getString
("CTL_Thread_stopped_no_source")).format (
new Object[] {
threadName,
className,
methodName,
lineNumber
}
),
ERR_OUT + STL_OUT
);
}
} else
println (
new MessageFormat (bundle.getString ("CTL_Thread_stopped")).
format (
new Object[] {
threadName,
className,
methodName,
lineNumber
}
),
ERR_OUT + STL_OUT
);
// refresh all
JPDAThread tt = threadManager.getThread (tr);
tt.setCurrent (true);
updateWatches ();
}
});
}
/**
* Second part of debugger start procedure.
*/
private void startDebugger () {
threadManager = new ThreadManager (this);
setBreakpoints ();
updateWatches ();
println (bundle.getString ("CTL_Debugger_running"), STL_OUT);
setDebuggerState (DEBUGGER_RUNNING);
virtualMachine.resume ();
// start refresh thread .................................................
if (debuggerThread != null) debuggerThread.stop ();
debuggerThread = new Thread (new Runnable () {
public void run () {
for (;;) {
try {
Thread.sleep (5000);
} catch (InterruptedException ex) {}
if (getState () == DEBUGGER_RUNNING)
threadGroup.refresh ();
}
}}, "Debugger refresh thread"); // NOI18N
debuggerThread.setPriority (Thread.MIN_PRIORITY);
debuggerThread.start ();
}
/**
* Removes last step request.
*/
void removeStepRequest () {
if (stepRequest != null) {
requestManager.deleteEventRequest (stepRequest);
stepRequest = null;
}
if (findSourceMER != null) {
requestManager.deleteEventRequest (findSourceMER);
findSourceMER = null;
}
if (findSourceSR != null) {
requestManager.deleteEventRequest (findSourceSR);
findSourceSR = null;
}
}
private static String generatePassword () {
StringBuffer sb = new StringBuffer ();
for (int i = 0; i < 4; i++)
sb.append ((char) (random.nextInt (26) + 'a'));
return new String (sb);
}
private VirtualMachine launch (DebuggerInfo info) throws DebuggerException {
// create process & read password for local debugging
// create main class & arguments ...............................................
StringBuffer sb = new StringBuffer ();
sb.append (mainClassName);
String[] infoArgs = info.getArguments ();
int i, k = infoArgs.length;
for (i = 0; i < k; i++)
sb.append (" \"").append (infoArgs [i]).append ('"'); // NOI18N
String main = new String (sb);
// create connector ..............................................................
VirtualMachineManager vmm = Bootstrap.virtualMachineManager ();
java.util.List lcs = vmm.launchingConnectors ();
k = lcs.size ();
for (i = 0; i < k; i++)
if ( ((LaunchingConnector) lcs.get (i)).name ().
indexOf ("RawCommandLineLaunch") >= 0
) // NOI18N
break;
if (i == k) {
finishDebugger ();
throw new DebuggerException (
new MessageFormat (bundle.getString ("EXC_Cannot_find_launcher")).
format (new Object[] {
"RawCommandLineLaunch" // NOI18N
})
);
}
LaunchingConnector lc = (LaunchingConnector) lcs.get (i);
String transport = lc.transport ().name ();
// create commandLine & NbProcessDescriptor ..............................
NbProcessDescriptor debugerProcess;
if (info instanceof ProcessDebuggerInfo)
debugerProcess = ((ProcessDebuggerInfo) info).getDebuggerProcess ();
else
debugerProcess = ProcessDebuggerType.DEFAULT_DEBUGGER_PROCESS;
// generate password
String password;
if (transport.equals ("dt_shmem")) { // NOI18N
connector = getAttachingConnectorFor ("dt_shmem");
password = generatePassword ();
args = connector.defaultArguments ();
((Argument) args.get ("name")).setValue (password);
} else {
try {
java.net.ServerSocket ss = new java.net.ServerSocket (0);
password = "" + ss.getLocalPort (); // NOI18N
ss.close ();
} catch (java.io.IOException e) {
finishDebugger ();
throw new DebuggerException (
new MessageFormat (
bundle.getString ("EXC_Cannot_find_empty_local_port")
).format (new Object[] {
e.toString ()
})
);
}
connector = getAttachingConnectorFor ("dt_socket");
args = connector.defaultArguments ();
((Argument) args.get ("port")).setValue (password);
}
HashMap map = Utils.processDebuggerInfo (
info,
"-Xdebug -Xnoagent -Xrunjdwp:transport=" + // NOI18N
transport +
",address=" + // NOI18N
password +
",suspend=y ", // NOI18N
main
);
MapFormat format = new MapFormat (map);
String commandLine = format.format (
debugerProcess.getProcessName () + " " + // NOI18N
debugerProcess.getArguments ()
);
println (commandLine, ERR_OUT);
/*
We mus wait on process start to connect...
try {
process = debugerProcess.exec (format);
} catch (java.io.IOException exc) {
finishDebugger ();
throw new DebuggerException (
new MessageFormat (bundle.getString ("EXC_While_create_debuggee")).
format (new Object[] {
debugerProcess.getProcessName (),
exc.toString ()
}),
exc
);
}
return connect (
null,
connector,
args
);*/
/* S ystem.out.println ("attaching: ");
Utils.showConnectors (vmm.attachingConnectors ());
S ystem.out.println ("launching: ");
Utils.showConnectors (vmm.launchingConnectors ());
S ystem.out.println ("listening: ");
Utils.showConnectors (vmm.listeningConnectors ());*/
// set debugger-start arguments
Map params = lc.defaultArguments ();
((Argument) params.get ("command")).setValue ( // NOI18N
commandLine
);
((Argument) params.get ("address")).setValue ( // NOI18N
password
);
// launch VM
try {
return lc.launch (params);
} catch (VMStartException exc) {
showOutput (process = exc.process (), ERR_OUT, ERR_OUT);
finishDebugger ();
throw new DebuggerException (
new MessageFormat (bundle.getString ("EXC_While_create_debuggee")).
format (new Object[] {
format.format (debugerProcess.getProcessName ()),
exc.toString ()
}),
exc
);
} catch (Exception exc) {
finishDebugger ();
throw new DebuggerException (
new MessageFormat (bundle.getString ("EXC_While_create_debuggee")).
format (new Object[] {
format.format (debugerProcess.getProcessName ()),
exc.toString ()
}),
exc
);
}
}
private VirtualMachine reconnect (ReconnectDebuggerInfo info)
throws DebuggerException {
return connect (
"CTL_Reconnecting_to",
info.getConnector (),
info.getArgs ()
);
}
private VirtualMachine connect (RemoteDebuggerInfo info)
throws DebuggerException {
return connect (
"CTL_Connecting_to",
connector = info.getConnector (),
args = info.getArgs ()
);
}
private VirtualMachine connect (
String bndlPrefix,
AttachingConnector connector,
Map args
) throws DebuggerException {
if (bndlPrefix != null) {
if (connector.transport ().name ().equals ("dt_shmem")) {
Argument a = (Argument) args.get ("name");
if (a == null)
println (bundle.getString (bndlPrefix + "_shmem_noargs"), ERR_OUT);
else
println (
new MessageFormat (bundle.getString (bndlPrefix + "_shmem")).
format (new Object[] {
a.value ()
}),
ERR_OUT
);
} else
if (connector.transport ().name ().equals ("dt_socket")) {
Argument name = (Argument) args.get ("hostname");
Argument port = (Argument) args.get ("port");
if ((name == null) || (port== null))
println (bundle.getString (bndlPrefix + "_socket_noargs"), ERR_OUT);
else
println (
new MessageFormat (bundle.getString (bndlPrefix + "_socket")).
format (new Object[] {
name.value (),
port.value ()
}),
ERR_OUT
);
} else
println (bundle.getString (bndlPrefix), ERR_OUT);
}
// launch VM
try { //S ystem.out.println ("attach to:" + ac + " : " + password); // NOI18N
return connector.attach (args);
} catch (Exception e) {
finishDebugger ();
throw new DebuggerException (
new MessageFormat (bundle.getString ("EXC_While_connecting_to_debuggee")).
format (new Object[] {
e.toString ()
}),
e
);
}
}
/**
* Performs stop action.
*/
void stop (boolean stop, final AbstractThread thread) {
final ResourceBundle bundle = NbBundle.getBundle (JPDADebugger.class);
if (stop) {
removeStepRequest ();
setLastAction (ACTION_BREAKPOINT_HIT);
setDebuggerState (DEBUGGER_STOPPED);
operator.stopRequest ();
SwingUtilities.invokeLater (new Runnable () {
public void run () {
thread.setCurrent (true);
updateWatches ();
threadGroup.refresh ();
}
});
} else
operator.resume ();
}
private static AttachingConnector getAttachingConnectorFor (String transport) {
List acs = Bootstrap.virtualMachineManager ().
attachingConnectors ();
AttachingConnector ac;
int i, k = acs.size ();
for (i = 0; i < k; i++)
if ( (ac = (AttachingConnector) acs.get (i)).transport ().
name ().equals (transport)
) return ac;
return null;
}
/**
* Setter method for debugger state property.
*
* @param newState
*/
synchronized public void setDebuggerState (final int newState) {
super.setDebuggerState (newState);
}
// innerclasses ..............................................................
private class ReconnectDebuggerInfo extends RemoteDebuggerInfo {
private ReconnectDebuggerInfo (
AttachingConnector connector,
Map args
) {
super (connector, args);
}
}
class Connector extends JPanel implements DebuggerInfoProducer,
ActionListener {
private JComboBox cbConnectors;
private Map args;
private java.util.List acs;
private JTextField[] tfParams;
private AttachingConnector ac;
Connector () {
VirtualMachineManager vmm = Bootstrap.virtualMachineManager ();
acs = vmm.attachingConnectors ();
setLayout (new GridBagLayout ());
refresh (0);
}
private void refresh (int index) {
GridBagConstraints c = new GridBagConstraints ();
// No connector ................
if (acs.size () == 0) {
add (new JLabel (bundle.getString ("CTL_No_Connector")), c);
return;
}
// Connector switch ................
if (acs.size () > 1) {
c.insets = new Insets (0, 0, 3, 3);
add (new JLabel (
bundle.getString ("CTL_Connector")
), c);
cbConnectors = new JComboBox ();
int i, k = acs.size ();
for (i = 0; i < k; i++) {
AttachingConnector ac = (AttachingConnector) acs.get (i);
int jj = ac.name ().lastIndexOf ('.');
String s = (jj < 0) ? ac.name () : ac.name ().substring (jj + 1);
cbConnectors.addItem (s + " (" + ac.description () + ")");
}
c = new GridBagConstraints ();
c.insets = new Insets (0, 3, 3, 0);
c.weightx = 1.0;
c.fill = java.awt.GridBagConstraints.HORIZONTAL;
c.gridwidth = 0;
cbConnectors.setSelectedIndex (index);
cbConnectors.setActionCommand ("SwitchMe!");
cbConnectors.addActionListener (this);
add (cbConnectors, c);
}
ac = (AttachingConnector) acs.get (index);
// Transport ................
c = new GridBagConstraints ();
c.insets = new Insets (3, 0, 0, 3);
add (new JLabel (bundle.getString ("CTL_Transport")), c);
JTextField tfTransport = new JTextField (ac.transport ().name ());
tfTransport.setEnabled (false);
c = new GridBagConstraints ();
c.gridwidth = 0;
c.insets = new Insets (3, 3, 0, 0);
c.fill = java.awt.GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
add (tfTransport, c);
// Other params ................
args = ac.defaultArguments ();
tfParams = new JTextField [args.size ()];
Iterator it = args.keySet ().iterator ();
int i = 0;
while (it.hasNext ()) {
String name = (String) it.next ();
Argument a = (Argument) args.get (name);
c = new GridBagConstraints ();
c.insets = new Insets (6, 0, 0, 3);
c.anchor = GridBagConstraints.WEST;
add (new JLabel (a.label () + ": "), c);
JTextField tfParam = new JTextField (a.value ());
tfParams [i ++] = tfParam;
tfParam.setName (name);
c = new GridBagConstraints ();
c.gridwidth = 0;
c.insets = new Insets (6, 3, 0, 0);
c.fill = java.awt.GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
add (tfParam, c);
}
c = new GridBagConstraints ();
c.weighty = 1.0;
JPanel p = new JPanel ();
p.setPreferredSize (new Dimension (1, 1));
add (p, c);
}
/**
* Returns DebuggerInfo.
*/
public DebuggerInfo getDebuggerInfo () {
int i, k = tfParams.length;
for (i = 0; i < k; i++) {
Argument a = (Argument) args.get (tfParams [i].getName ());
a.setValue (tfParams [i].getText ());
}
return new RemoteDebuggerInfo (ac, args);
}
public void actionPerformed (ActionEvent e) {
removeAll ();
refresh (((JComboBox) e.getSource ()).getSelectedIndex ());
Component w = getParent ();
while (!(w instanceof Window))
w = w.getParent ();
if (w != null) ((Window) w).pack (); // ugly hack...
return;
}
private String translate (String name) {
/* if (name.equals ("SwitchMe!"))
return
else*/
return name;
}
}
}
/*
* Log
* 22 Gandalf 1.21 01/14/00 Daniel Prusa NOI18N
* 21 Gandalf 1.20 01/13/00 Daniel Prusa NOI18N
* 20 Gandalf 1.19 01/06/00 Jan Jancura Refresh of Threads &
* Watches, Weakization of Nodes
* 19 Gandalf 1.18 12/07/99 Daniel Prusa getLastAtion renamed to
* getLastAction
* 18 Gandalf 1.17 11/29/99 Jan Jancura Bug 3341 - bad \n in output
* of debugger
* Bug 3930 - comments of exceptions thrown while starting of debugger
* Some implementation moved to AbstractDebugger
* Support for TraceInto - finding source.
* 17 Gandalf 1.16 11/08/99 Jan Jancura Somma classes renamed
* 16 Gandalf 1.15 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 15 Gandalf 1.14 10/15/99 Jan Jancura Bug with launching JPDA on
* Solaris.
* 14 Gandalf 1.13 10/13/99 Jan Jancura Destroy action
* bug in deleting watches
* deserializing of main window
* 13 Gandalf 1.12 10/07/99
*/